package net.disy.cadenza.repository.wrappers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import net.disy.cadenza.repository.selector.ResultObjectTypes;
import net.disy.cadenza.repositorytree.schema.Item;
import net.disy.cadenza.schema.selection.Condition;
import net.disy.cadenza.schema.selection.ConditionAttribute;
import net.disy.cadenza.schema.selection.Contains;
import net.disy.cadenza.schema.selection.Default;
import net.disy.cadenza.schema.selection.EntryValue;
import net.disy.cadenza.schema.selection.ResultAttribute;
import net.disy.cadenza.schema.selection.Selector;

public class SelectorWrapper {
	private Selector selector;
	private SelectorWrapper baseSelector;
	private String name;
	private Map<String, Contains> containsCondtions;
	private Set<String> objectTypeNames;
	private Item item;
	
	public SelectorWrapper(Selector selector, String name){
		this.selector = selector;
		this.name = name;
		init(selector);
	}
	public SelectorWrapper(Selector selector, Map<String, List<Default>> containsConditionDefaults, String name,  SelectorWrapper baseSelector){
		this.selector = selector;
		this.baseSelector = baseSelector;
		this.name = name;
		this.containsCondtions = baseSelector.getContainsConditions();
		this.objectTypeNames = baseSelector.getObjectTypeNames();
		for(String conditionName : containsConditionDefaults.keySet()){
			Contains baseContainsCondition = this.containsCondtions.get(conditionName);
			baseContainsCondition.getCondition().getDefault().addAll(containsConditionDefaults.get(conditionName));
		}
	}
	
	public Item getItem() {
		return item;
	}
	public void setItem(Item item) {
		this.item = item;
	}
	private void init(Selector selector){
		objectTypeNames = new HashSet<String>();
		for(ResultAttribute resultAttribute : selector.getResultAttributes().getResultAttribute()){
			String objectTypePath = resultAttribute.getObjectTypePath();
			StringTokenizer stringTokenizer = new StringTokenizer(objectTypePath, ":");
			while(stringTokenizer.hasMoreTokens()){
				objectTypeNames.add(stringTokenizer.nextToken());
			}
		}
		containsCondtions = new HashMap<String, Contains>();
		for(Object selectorContainsCondition : selector.getContainsOrConditionGroup()){
			if(selectorContainsCondition instanceof Contains){
				Contains containsCondition = (Contains)selectorContainsCondition;
				containsCondtions.put(containsCondition.getConditionName(), containsCondition);
				Condition condition = containsCondition.getCondition();
				String conditionObjectTypePath = condition.getConditionObjectType().getObjectTypePath();
				StringTokenizer st = new StringTokenizer(conditionObjectTypePath, ":");
				while(st.hasMoreTokens())
					objectTypeNames.add(st.nextToken());
//				if(condition instanceof DateCondition){
//					DateCondition dateCondition = (DateCondition)condition;
//					String dateFormat = dateCondition.getDateFormat();
//				}
			}
		}
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public boolean isBaseSelector(){
		return baseSelector == null;
	}
	
	
	public Selector getSelector() {
		return selector;
	}

	public void setSelector(Selector selector) {
		this.selector = selector;
	}

	public SelectorWrapper getBaseSelector() {
		return baseSelector;
	}

	public Map<String, Contains> getContainsConditions(){
		return containsCondtions;
	}
	
	public Set<String> getObjectTypeNames(){
		return objectTypeNames;
	}
	
	public String getURL(){
		return item.getId();
	}
	
	public boolean isSatisfyingResultObjectTypes(ResultObjectTypes resultObjectTypes){
		if(isBaseSelector()){
			for(String keyword : resultObjectTypes.getKeywordToObjectAttributes().keySet()){
				Set<String> objectAttributesToKeyword = resultObjectTypes.getKeywordToObjectAttributes().get(keyword);
				boolean satisfyKeywordCondition = false;
				for(Contains contains : getContainsConditions().values()){
					for(ConditionAttribute conditionAttribute : contains.getCondition().getConditionAttribute()){
						if(objectAttributesToKeyword.contains(conditionAttribute.getAttributeName())){
							satisfyKeywordCondition = true;
							break;
						}
					}
					if(satisfyKeywordCondition)
						break;
				}
				if(!satisfyKeywordCondition)
					return false;
			}
			return true;
		}
		for(Contains contains : getContainsConditions().values()){
			List<Default> defaults = contains.getCondition().getDefault();
			if(defaults.size() != 0){
				boolean defaultConditionSatisfyied = false;
				for(Default defaultCondition : defaults){
					EntryValue defaultEntryValue = defaultCondition.getValue().get(0);
					String attributeName = defaultEntryValue.getAttribute();
					String attributeValue = defaultEntryValue.getValue();
					defaultConditionSatisfyied = resultObjectTypes.hasAttributeWithValue(attributeName, attributeValue);
					if(defaultConditionSatisfyied){
						defaultConditionSatisfyied = true;
						break;
					}
				}
				if(!defaultConditionSatisfyied)
					return false;
			}
			
		}
		return true;
	}
	
//	public boolean isSatisfyingCondition(ObjectTypeCondition objectTypeCondition ){
//		Map<String, Boolean> satisfiedObjectTypeConditionAttributes = new HashMap<String, Boolean>();
//		for(String objectTypeConditionAttribute : objectTypeCondition.getAttributeNames()){
//			satisfiedObjectTypeConditionAttributes.put(objectTypeConditionAttribute, false);
//		}
//		for(Contains contaions : containsCondtions.values()){
//			Condition selectorCondition = contaions.getCondition();
//			String selectorConditionObjectType = selectorCondition.getConditionObjectType().getObjectTypePath();
//			if(selectorConditionObjectType.contains(":"))
//				selectorConditionObjectType = selectorConditionObjectType.substring(selectorConditionObjectType.lastIndexOf(":") + 1);
//			if(objectTypeCondition.getObjectTypeName().equalsIgnoreCase(selectorConditionObjectType)){
//				if(selectorCondition.getDefault().size() != 0){
//					List<Default> selectorConditionDefaults = selectorCondition.getDefault();
//					for(String objectTypeConditionAttribute : objectTypeCondition.getAttributeNames()){
//						boolean isConditionSatisfied = false;
//						List<String> objectTypeConditionAttributeValues = objectTypeCondition.getAttributeValuesMap().get(objectTypeConditionAttribute);
//						for(Default selectorConditionDefault : selectorConditionDefaults){
//							for(EntryValue selectorConditionDefaultEntryValue : selectorConditionDefault.getValue()){
//								if(objectTypeConditionAttribute.equalsIgnoreCase(selectorConditionDefaultEntryValue.getAttribute())){
//									boolean satisfyObjectTypeCondition = objectTypeConditionAttributeValues.contains(selectorConditionDefaultEntryValue.getValue());
//									satisfiedObjectTypeConditionAttributes.put(objectTypeConditionAttribute, satisfyObjectTypeCondition);
//									if(satisfyObjectTypeCondition){
//										isConditionSatisfied = true;
//										break;
//									}
//								}
//							}
//							if(isConditionSatisfied)
//								break;
//						}
//						
//					}
//				}else{
//					for(ConditionAttribute selectorConditionAttribute : selectorCondition.getConditionAttribute()){
//						String selectorConditionAttributeName = selectorConditionAttribute.getAttributeName();
//						if(satisfiedObjectTypeConditionAttributes.containsKey(selectorConditionAttributeName))
//							satisfiedObjectTypeConditionAttributes.put(selectorConditionAttributeName, true);
//					}
//				}
//			}
//		}
//		boolean isSatisfied = true;
//		for(boolean isAttributeSatisfied : satisfiedObjectTypeConditionAttributes.values())
//			isSatisfied = isSatisfied && isAttributeSatisfied;
//		
//		return isSatisfied;
//	}
}
